package orm.er;

import orm.infrastructure.interfaces.IAssignable;
import orm.infrastructure.interfaces.IBinarySerialize;
import orm.infrastructure.interfaces.INullable;
import orm.infrastructure.interfaces.IValidable;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * User: Awake
 * Date: 03.05.12
 * Time: 10:33
 * To change this template use File | Settings | File Templates.
 */
public class PhoneMock implements IAssignable, IValidable, INullable, IBinarySerialize, Cloneable {

    private static final int PHONE_LENGTH = 50;
    private static final String NULL_EXCEPTION = "Can not operate with null objects";
    private static final String NOT_VALID_EXCEPTION = "Can not operate with not valid object";
    private static final String ENCODING = "UTF-16";
    private static final int NULL_VALUE = -1;

    public PhoneMock() {

    }

    public PhoneMock(int phoneID, int personID, String phone) {
        this.m_phoneID = phoneID;
        this.m_personID = personID;
        this.m_phone = phone;
        this.m_nullable = false;
    }

    /**
     * Creates nullable instance of PhoneMock
     *
     * @return nullable PhoneMock object
     */

    public static PhoneMock getNullableInstance() {
        PhoneMock phoneMock = new PhoneMock();
        phoneMock.m_nullable = true;
        return phoneMock;
    }

    @Override
    public void assignTo(Object object) {

        if (object != null && object.getClass().equals(PhoneMock.class)) {

            PhoneMock phone = (PhoneMock) object;
            phone.setPhoneID(this.m_phoneID);
            phone.setPersonID(this.m_personID);
            phone.setPhone(this.m_phone);
        }
    }

    @Override
    public Object clone() {
        PhoneMock phone = new PhoneMock();
        this.assignTo(phone);
        return phone;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PhoneMock)) return false;

        PhoneMock phoneMock = (PhoneMock) o;

        if (m_personID != phoneMock.m_personID) return false;
        if (m_phoneID != phoneMock.m_phoneID) return false;
        if (m_phone != null ? !m_phone.equals(phoneMock.m_phone) : phoneMock.m_phone != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = m_phoneID;
        result = 31 * result + m_personID;
        result = 31 * result + (m_phone != null ? m_phone.hashCode() : 0);
        return result;
    }

    @Override
    public void writeTo(DataOutputStream outputStream) throws IOException {

        if (!this.Validate()) {
            throw new UnsupportedOperationException(NOT_VALID_EXCEPTION);
        } else {

            outputStream.writeInt(getPhoneID());
            outputStream.writeInt(getPersonID());
            if (m_phone == null) {
                outputStream.writeInt(NULL_VALUE);
            } else {
                byte[] phoneBinaryArray = getPhone().getBytes(ENCODING);
                outputStream.writeInt(phoneBinaryArray.length);
                outputStream.write(phoneBinaryArray);
            }
        }
    }

    @Override
    public void readFrom(DataInputStream inputStream) throws IOException {

        if (!this.Validate()) {
            throw new UnsupportedOperationException(NOT_VALID_EXCEPTION);
        } else {

            setPhoneID(inputStream.readInt());
            setPersonID(inputStream.readInt());
            int addressLength = inputStream.readInt();
            if (addressLength >= 0) {
                byte[] addressBytes = new byte[addressLength];
                inputStream.read(addressBytes, 0, addressLength);
                String phone = new String(addressBytes, ENCODING);
                setPhone(phone);
            } else {
                setPhone(null);
            }
        }
    }

    @Override
    public boolean isNullable() {
        return m_nullable;
    }

    @Override
    public boolean Validate() {
        return !(this == null || m_personID < 0 || m_phoneID < 0 || m_phone == null);
    }

    public int getPhoneID() {
        return m_phoneID;
    }

    public void setPhoneID(int phoneID) {
        if (m_nullable)
            throw new UnsupportedOperationException(NULL_EXCEPTION);
        this.m_phoneID = phoneID;
    }

    public int getPersonID() {
        return m_personID;
    }

    public void setPersonID(int personID) {
        if (m_nullable)
            throw new UnsupportedOperationException(NULL_EXCEPTION);
        this.m_personID = personID;
    }

    public String getPhone() {
        return m_phone;
    }

    public void setPhone(String phone) {
        if (m_nullable)
            throw new UnsupportedOperationException(NULL_EXCEPTION);

        this.m_phone = (phone.length() > PHONE_LENGTH) ? phone.substring(0, PHONE_LENGTH - 1) : phone;
    }

    private int m_phoneID;
    private int m_personID;
    private String m_phone;
    private boolean m_nullable;
}
